﻿using System.Collections;
using System.Collections.Generic;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;

namespace Ebt.Mvvm.Behaviors
{
    /// <summary>
    /// Allows to display the <see cref="PopupMenu"/> when the user taps or right clicks on a <see cref="UIElement"/>.
    /// </summary>
    /// <example>
    /// XAML
    /// &lt;Border Behaviors:ContextMenuBehavior.Commands="{Binding ContextMenuCommands}"/&gt;
    /// </example>
    public static class ContextMenuBehavior
    {
        public static readonly DependencyProperty CommandsProperty =
            DependencyProperty.RegisterAttached("Commands", typeof(IList), typeof(ContextMenuBehavior),
            new PropertyMetadata(null, OnCommandsChanged));

        public static void SetCommands(DependencyObject d, IList<UICommand> value)
        {
            d.SetValue(CommandsProperty, value);
        }

        public static IList<UICommand> GetCommands(DependencyObject d)
        {
            return (IList<UICommand>)d.GetValue(CommandsProperty);
        }

        private static void OnCommandsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d == null)
                return;

            var element = (UIElement) d;

            element.Tapped -= OnTapped;
            element.RightTapped -= OnRightTapped;

            element.Tapped += OnTapped;
            element.RightTapped += OnRightTapped;
        }

        private static void OnRightTapped(object sender, RightTappedRoutedEventArgs e)
        {
            var position = e.GetPosition(null);
            var d = (DependencyObject)sender;
            OpenMenu(d, position);
            e.Handled = true;
        }

        private static void OnTapped(object sender, TappedRoutedEventArgs e)
        {
            if(e.PointerDeviceType == PointerDeviceType.Mouse)
                return;

            var position = e.GetPosition(null);
            var d = (DependencyObject) sender;
            OpenMenu(d, position);
            e.Handled = true;
        }

        private static void OpenMenu(DependencyObject d, Point position)
        {
            var commands = GetCommands(d);

            if (commands == null || commands.Count == 0)
                return;

            var popupMenu = new PopupMenu();
            foreach (var command in commands)
            {
                popupMenu.Commands.Add(command);
            }
            popupMenu.ShowAsync(position);
        }

    }
}
